#include "GameHandler.h"
#include <stdio.h>
#include <stdlib.h>




#define TestMap

#ifdef TestMap
const string ThisMap = "Maps/Test.txt";
#endif
#ifdef InstantMap
const string ThisMap = "Maps/InstantWin.txt";
#endif
#ifdef DemoMap
const string ThisMap = "Maps/Demo.txt";
#endif

GameHandler::GameHandler()
{
	MoveMade = false;
};
//=====INIT MENU
void GameHandler::AddButton (Pair Pt, int Show,int Switch, char* Text)
{
	D3DSURFACE_DESC Dimensions;		
	GraphicsHandler::Into()->
		GetTexture(TEX_BUTTON)->
		GetLevelDesc(0,&Dimensions);

	Pair Dims((float)Dimensions.Width,(float)Dimensions.Height);
	Pair States((float)Show,(float)Switch);

	S_List.push_back(new Button(Pt,States,Dims,Text));
}
void GameHandler::AddPanel  (Pair Pt, int Show, char* Text)
{
	D3DSURFACE_DESC Dimensions;		
	GraphicsHandler::Into()->
		GetTexture(TEX_MENUPANE)->
		GetLevelDesc(0,&Dimensions);

	Pair Dims((float)Dimensions.Width,(float)Dimensions.Height);
	S_List.push_back(new Panel(Pt,Show,Dims,Text));
};
void GameHandler::AddSplash (Pair Pt, int Show)
{
	D3DSURFACE_DESC Dimensions;		
	GraphicsHandler::Into()->
		GetTexture(TEX_MENUPANE)->
		GetLevelDesc(0,&Dimensions);

	Pair Dims((float)Dimensions.Width,(float)Dimensions.Height);
	S_List.push_back(new Splash(Pt,Show,Dims));
}
void GameHandler::InitMenuObjects()
{
	//=====PLAY MENU
	char* Instructions =" N: Next Object\n B: Back Object\n Moving ends your turn\n Arrows/Page Keys for camera\n WASD keys to move object\n Q: Rotate AntiClockwise (Move)\n E: Rotate Clockwise (Move)\n";

	//=====PLAY MENU
	AddPanel (Pair(SCREEN_WIDTH*0.50f,SCREEN_HEIGHT*0.10f),ST_PLAY,Instructions);
	AddButton(Pair(SCREEN_WIDTH*0.65f,SCREEN_HEIGHT*0.05f),ST_PLAY,ST_OPTIONS,"Options");
	AddButton(Pair(SCREEN_WIDTH*0.65f,SCREEN_HEIGHT*0.15f),ST_PLAY,ST_RESET,"Reset");
	//=====OPTIONS MENU
	AddPanel (Pair(SCREEN_WIDTH*0.50f,SCREEN_HEIGHT*0.50f),ST_OPTIONS,"Options");
	AddButton(Pair(SCREEN_WIDTH*0.35f,SCREEN_HEIGHT*0.50f),ST_OPTIONS,ST_QUIT,"Quit");
	AddButton(Pair(SCREEN_WIDTH*0.50f,SCREEN_HEIGHT*0.50f),ST_OPTIONS,ST_MAIN,"Main");
	AddButton(Pair(SCREEN_WIDTH*0.65f,SCREEN_HEIGHT*0.50f),ST_OPTIONS,ST_PLAY,"Return");
	//=====MAIN MENU
	AddSplash(Pair(SCREEN_WIDTH*0.50f,SCREEN_HEIGHT*0.50f),ST_MAIN);
	AddPanel (Pair(SCREEN_WIDTH*0.50f,SCREEN_HEIGHT*0.10f),ST_MAIN,"Main Menu");
	AddButton(Pair(SCREEN_WIDTH*0.35f,SCREEN_HEIGHT*0.05f),ST_MAIN,ST_PLAY,"Play");
	AddButton(Pair(SCREEN_WIDTH*0.65f,SCREEN_HEIGHT*0.05f),ST_MAIN,ST_QUIT,"Quit");
	//=====GAMEWON1
	AddPanel (Pair(SCREEN_WIDTH*0.50f,SCREEN_HEIGHT*0.10f),ST_GAMEWON1,"Player1 Won");
	AddButton(Pair(SCREEN_WIDTH*0.65f,SCREEN_HEIGHT*0.05f),ST_GAMEWON1,ST_QUIT,"Quit");
	AddButton(Pair(SCREEN_WIDTH*0.65f,SCREEN_HEIGHT*0.15f),ST_GAMEWON1,ST_RESET,"Reset");
	//=====GAMEWON2
	AddPanel (Pair(SCREEN_WIDTH*0.50f,SCREEN_HEIGHT*0.10f),ST_GAMEWON2,"Player2 Won");
	AddButton(Pair(SCREEN_WIDTH*0.65f,SCREEN_HEIGHT*0.15f),ST_GAMEWON2,ST_RESET,"Reset");
	AddButton(Pair(SCREEN_WIDTH*0.65f,SCREEN_HEIGHT*0.05f),ST_GAMEWON2,ST_QUIT,"Quit");

}

//=====MAP READER/BUILDER
void GameHandler::BuildMap(LPCSTR FileName)
{
	Map.ReadMapFromText(FileName);

	SetDrawList();
}

void GameHandler::SetDrawList()
{
	//Add the arrow to point at our current selection//
	O_List.push_back(new BaseDrawable(D3OBJ_ARROW,D3DXVECTOR3((float)NowCoord.X,1.8f,-(float)(NowCoord.Y)),0,PlayerTurn));

	
	for(int y = 0; y < Map.GetHeight(); ++y)
	{
		for(int x = 0; x < Map.GetWidth(); ++x)
		{
			//Board Square
			O_List.push_back(new BaseDrawable(D3OBJ_CHIT,D3DXVECTOR3((float)(x),0,-(float)(y)),DIR_NORTH,Map.GetMapData(x,y).Owner));
		}
	}



	for(int y = 0; y < Map.GetHeight(); ++y)
	{
		for(int x = 0; x < Map.GetWidth(); ++x)
		{
			switch(Map.GetMapData(x,y).Object)
			{

			case D3OBJ_SPHINX:	 O_List.push_back(new BaseDrawable(D3OBJ_SPHINX,D3DXVECTOR3((float)(x),0,-(float)(y)),
								  Map.GetMapData(x,y).Direction,Map.GetMapData(x,y).Owner));
				break;
			case D3OBJ_PHARAOH:	 O_List.push_back(new BaseDrawable(D3OBJ_PHARAOH,D3DXVECTOR3((float)(x),0,-(float)(y)),
								  Map.GetMapData(x,y).Direction,Map.GetMapData(x,y).Owner));
				break;
			case D3OBJ_ANUBIS:	 O_List.push_back(new BaseDrawable(D3OBJ_ANUBIS,D3DXVECTOR3((float)(x),0,-(float)(y)),
								  Map.GetMapData(x,y).Direction,Map.GetMapData(x,y).Owner));
				break;
			case D3OBJ_PYRAMID:	 O_List.push_back(new BaseDrawable(D3OBJ_PYRAMID,D3DXVECTOR3((float)(x),0,-(float)(y)),
								  Map.GetMapData(x,y).Direction,Map.GetMapData(x,y).Owner));
				break;
			case D3OBJ_SCARAB:  O_List.push_back(new BaseDrawable(D3OBJ_SCARAB,D3DXVECTOR3((float)(x),0,-(float)(y)),
								  Map.GetMapData(x,y).Direction,Map.GetMapData(x,y).Owner));
				break;
			}
		}	//end for(x)
	}	//end for (y)
}
//=====INITIALIZATION
void GameHandler::Init(HWND hWnd, HINSTANCE hInstance, bool WndOpen)
{
	GraphicsHandler::Into()->Initialize(hWnd, hInstance,true);
	DirectInput::Into()->Init(hInstance, hWnd);
	Timer::Into()->Init();
	GameState = ST_MAIN;
	NowCoord.X = 0;
	NowCoord.Y = 0;
	PlayerTurn = Player1;

	BuildMap(ThisMap.c_str());

	InitMenuObjects();
	Sounds.LoadSounds("Sounds");
}
//=====INPUT
void GameHandler::NextObject()
{
	bool FoundObject = false;
	while(!FoundObject)
	{
		NowCoord.X++;
		if(NowCoord.X >= Map.GetWidth())
		{
			NowCoord.X = 0;
			NowCoord.Y++;
			if(NowCoord.Y >= Map.GetHeight())
				NowCoord.Y = 0;
		}	//end if(x >= Width)
		if(Map.GetMapData ((int)NowCoord.X, (int)NowCoord.Y).Owner == PlayerTurn &&	//Only current player's objects
			Map.GetMapData((int)NowCoord.X, (int)NowCoord.Y).Object > D3OBJ_LASER &&//Pass Empty, Chit, Arrow, and Laser
			Map.GetMapData((int)NowCoord.X, (int)NowCoord.Y).Object < D3OBJ_SIZE)	//Stop at size
			FoundObject = true;

	}	//end while(Object not found)
	MoveMade = false;

};
void GameHandler::BackObject()
{
	bool FoundObject = false;

	while(!FoundObject)
	{
		NowCoord.X--;
		if(NowCoord.X < 0)
		{
			NowCoord.X = (float)Map.GetWidth()-1;
			NowCoord.Y--;

		}	//end if(x >= Width)
		if(NowCoord.Y <= 0)
			NowCoord.Y = (float)(Map.GetHeight() -1);
		if(Map.GetMapData ((int)NowCoord.X, (int)NowCoord.Y).Owner == PlayerTurn &&	//Only current player's objects
			Map.GetMapData((int)NowCoord.X, (int)NowCoord.Y).Object > D3OBJ_LASER &&//Pass Empty, Chit, Arrow, and Laser
			Map.GetMapData((int)NowCoord.X, (int)NowCoord.Y).Object < D3OBJ_SIZE)	//Stop at size
			FoundObject = true;
	}
}
void GameHandler::NextPlayer()
{
	if(GameState == ST_PLAY){
		for(int y = 0; y < Map.GetHeight(); ++y){
			for(int x = 0; x < Map.GetWidth(); ++x){
				if(Map.GetMapData(x,y).Object == D3OBJ_SPHINX && Map.GetMapData(x,y).Owner == PlayerTurn)
					switch(Map.GetMapData(x,y).Direction)
				{
					case DIR_NORTH:	GameLaser.FireLaser((float)x, (float)(-(y-1)), Map.GetMapData(x,y).Direction, PlayerTurn);
						break;
					case DIR_EAST:	GameLaser.FireLaser((float)(x+1), (float)(-(y)), Map.GetMapData(x,y).Direction, PlayerTurn);
						break;
					case DIR_SOUTH:	GameLaser.FireLaser((float)(x), (float)(-(y+1)), Map.GetMapData(x,y).Direction, PlayerTurn);
						break;
					case DIR_WEST:	GameLaser.FireLaser((float)(x-1), (float)(-(y)), Map.GetMapData(x,y).Direction, PlayerTurn);
						break;
				}//EndSwitch
			}//Endfor
		}//Endfor

		(PlayerTurn == 1? PlayerTurn = 2 : PlayerTurn = 1);		//Turn has ended, switch players
		GameState = ST_LASER;									//Turn has ended, switch to laser state
	}//Endif

	if(GameState == ST_GAMEWON1 || GameState ==ST_GAMEWON2)
	{
		Map.ClearMap();
		NowCoord.X = 0;
		NowCoord.Y = 0;
		Map.ReadMapFromText(ThisMap.c_str());

		PlayerTurn = 1;
		GameState = ST_PLAY;
	}

};
void GameHandler::Move(int Dir)
{
	if(Map.GetMapData((int)NowCoord.X,(int)NowCoord.Y).Object != D3OBJ_SPHINX)
	{
		if(Map.MoveObject((int)NowCoord.X,(int)NowCoord.Y, Dir))
		{
			switch(Dir)
			{
			case DIR_NORTH: NowCoord.Y++; break;
			case DIR_SOUTH: NowCoord.Y--; break;
			case DIR_WEST:  NowCoord.X--; break;
			case DIR_EAST:  NowCoord.X++; break;
			}//Endswitch
			MoveMade = true;
		}//Endif

	}//Endif
};
void GameHandler::Rotate(int Dir)
{
	Map.RotateObject((int)NowCoord.X,(int)NowCoord.Y, Dir);
	MoveMade = true;
};
void GameHandler::ButtonClick()
{
	//If we click a button we want to switch to that button's state
	for(unsigned int i = 0; i < S_List.size();i++)								//For Each Sprite		
		if(S_List[i]->getObjID() == TEX_BUTTON)									//That is a button
			if(S_List[i]->GetShowState() == GameState)							//If that button is visible
				if(S_List[i]->CheckBounds(DirectInput::Into()->GetCursor())){	//See if we've clicked
					GameState = S_List[i]->GetSwitchState();					//Switch to that state
					Sounds.PlayCue("Click");
				}
}
void GameHandler::Input()
{
	if(DirectInput::Into()->MouseDown(LEFT))	ButtonClick();
	if(GameState == ST_PLAY)
	{
		if(DirectInput::Into()->KeyOnce(DIK_W))		Move(DIR_NORTH);
		if(DirectInput::Into()->KeyOnce(DIK_S))		Move(DIR_SOUTH);
		if(DirectInput::Into()->KeyOnce(DIK_A))		Move(DIR_WEST);
		if(DirectInput::Into()->KeyOnce(DIK_D))		Move(DIR_EAST);

		if(DirectInput::Into()->KeyOnce(DIK_Q))		Rotate(DIR_WEST);
		if(DirectInput::Into()->KeyOnce(DIK_E))		Rotate(DIR_EAST);

		if(DirectInput::Into()->KeyOnce(DIK_N))		NextObject();
		if(DirectInput::Into()->KeyOnce(DIK_B))		BackObject();
	}
}
//=====UPDATE
bool GameHandler::Update(HWND hWnd)
{
	O_List.clear();

	if(MoveMade)
	{
		MoveMade = false;
		NextPlayer();
	}

	if(GameState== ST_QUIT)
		return false;
	/*Set the original position and rotation of the object to 
	Limit the player from moving or rotating more than one space or unit per turn
	*/
	if(Map.GetMapData((int)NowCoord.X,(int)NowCoord.Y).Object == D3OBJ_SPHINX)
		NextObject();
	if(Map.GetMapData((int)NowCoord.X,(int)NowCoord.Y).Owner != PlayerTurn)
		NextObject();



	GraphicsHandler::Into()->Update(O_List);
	DirectInput::Into()->UpdateInput(hWnd);
	Timer::Into()->Update();

	if(GameState == ST_LASER)
	{
		GameLaser.Update();
		//Returns true is game is won.
		if(GameLaser.Reflect(Map.GetMapData((int)GameLaser.GetX(), -(int)GameLaser.GetZ()).Object,
			Map.GetMapData((int)GameLaser.GetX(), -(int)GameLaser.GetZ()).Direction))
		{
			if(PlayerTurn ==2)
				GameState = ST_GAMEWON1;
			else GameState = ST_GAMEWON2;
		}
		O_List.push_back(&GameLaser);
	}

	if(GameState == ST_RESET)
	{
		Map.ClearMap();
		NowCoord.X = 0;
		NowCoord.Y = 0;

		Map.ReadMapFromText(ThisMap.c_str());
		PlayerTurn = 1;
		GameState = ST_PLAY;
	}


	SetDrawList();
	return true;
}
//=====RENDER
void GameHandler::Render()
{
	GraphicsHandler::Into()->Draw(O_List,S_List,GameState);
}